package com.kuzan.autocloud.gateway.filter;

import com.google.gson.Gson;
import com.kuzan.autocloud.common.model.log.LogOriginal;
import com.kuzan.autocloud.common.repository.log.LogOriginalRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

import static com.kuzan.autocloud.common.Constant.*;

/**
 * <p>Description: 请求时间和日志拦截</p>
 *
 * @author kuzank
 */
public class RequestTimeGatewayFilterFactory extends AbstractGatewayFilterFactory<RequestTimeGatewayFilterFactory.Config> {

    private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
    private static final String KEY = "withParams";

    @Autowired
    LogOriginalRepository logOriginalRepository;

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(KEY);
    }

    public RequestTimeGatewayFilterFactory() {
        super(Config.class);
    }

    Gson gson = new Gson();


    /**
     * 将进入系统的每个请求详情信息都记录到数据库中
     */
    @Override
    public GatewayFilter apply(Config config) {

        return (exchange, chain) -> {

            Object requestBody = exchange.getAttribute("cachedRequestBodyObject");
            final String body = requestBody != null ? gson.toJson(requestBody) : null;

            exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());

            return chain.filter(exchange).then(
                    Mono.fromRunnable(() -> {

                        Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);

                        if (startTime != null) {
                            HttpHeaders headers = exchange.getRequest().getHeaders();

                            String url = exchange.getRequest().getURI().getRawPath();
                            double elapsedtime = System.currentTimeMillis() - startTime;
                            String ipaddress = exchange.getRequest().getRemoteAddress().getHostString();

                            String origin = null == headers.get("Origin") ? "" : String.join(",", headers.get("Origin"));
                            String agentt = null == headers.get("User-Agent") ? "" : String.join(",", headers.get("User-Agent"));
                            String langua = null == headers.get("Accept-Language") ? "" : String.join(",", headers.get("Accept-Language"));
                            String organi = null == headers.get(AuthorizationOrganization) ? "" : String.join(",", headers.get(AuthorizationOrganization));
                            String person = null == headers.get(AuthorizationPerson) ? "" : String.join(",", headers.get(AuthorizationPerson));

                            LogOriginal logOriginal = LogOriginal.builder()
                                    .url(url)
                                    .elapsedtime(elapsedtime)
                                    .ipaddress(ipaddress)
                                    .origin(origin)
                                    .agent(agentt)
                                    .language(langua)
                                    .organization(organi)
                                    .body(body)
                                    .build();
                            logOriginal.setCreator(person);
                            logOriginalRepository.save(logOriginal);
                        }
                    })
            );
        };
    }


    public static class Config {

        private boolean withParams;

        public boolean isWithParams() {
            return withParams;
        }

        public void setWithParams(boolean withParams) {
            this.withParams = withParams;
        }

    }
}
